package com.xc.ezplan.core.utils;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.PutObjectRequest;
import com.xc.ezplan.core.domain.AliStorageConfig;
import com.xc.ezplan.core.enums.AliEndpointEnum;
import com.xc.ezplan.core.exception.BadRequestException;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.Collection;
import java.util.List;

/**
 * @author lixingchen
 * @date 2022/12/03
 * @description 阿里云存储工具类
 */
@Slf4j
public class AliCloudUtil {

	private static final String PACKAGE_NAME = "avatar/";

	public static void upload(AliStorageConfig aliStorageConfig, String fileName, byte[] bytes) {
		OSS ossClient = new OSSClientBuilder().build(AliEndpointEnum.find(aliStorageConfig.getEndpoint()),
				aliStorageConfig.getAccessKeyId(), aliStorageConfig.getAccessKeySecret());
		try {
			// 上传文件。
			ossClient.putObject(aliStorageConfig.getBucket(), PACKAGE_NAME+fileName,new ByteArrayInputStream(bytes));
		} catch (OSSException oe) {
			log.error("Caught an OSSException, which means your request made it to OSS, "
					+ "but was rejected with an error response for some reason.");
			log.error("Error Message:" + oe.getErrorMessage());
			log.error("Error Code:" + oe.getErrorCode());
			log.error("Request ID:" + oe.getRequestId());
			log.error("Host ID:" + oe.getHostId());
			throw new BadRequestException("Error Message:" +oe.getMessage());
		} catch (ClientException ce) {
			log.error("Caught an ClientException, which means the client encountered "
					+ "a serious internal problem while trying to communicate with OSS, "
					+ "such as not being able to access the network.");
			log.error("Error Message:" + ce.getMessage());
			throw new BadRequestException("Error Message:" +ce.getMessage());
		} finally {
			if (ossClient != null) {
				ossClient.shutdown();
			}
		}
	}

	public static void download(AliStorageConfig aliStorageConfig, String fileName, File file) {

		// 创建OSSClient实例。
		OSS ossClient = new OSSClientBuilder().build(AliEndpointEnum.find(aliStorageConfig.getEndpoint()),
				aliStorageConfig.getAccessKeyId(), aliStorageConfig.getAccessKeySecret());

		try {
			// 下载Object到本地文件，并保存到指定的本地路径中。如果指定的本地文件存在会覆盖，不存在则新建。
			// 如果未指定本地路径，则下载后的文件默认保存到示例程序所属项目对应本地路径中。
			ossClient.getObject(new GetObjectRequest(aliStorageConfig.getBucket(), fileName), file);
		} catch (OSSException oe) {
			log.error("Caught an OSSException, which means your request made it to OSS, "
					+ "but was rejected with an error response for some reason.");
			log.error("Error Code:" + oe.getErrorCode());
			log.error("Request ID:" + oe.getRequestId());
			log.error("Host ID:" + oe.getHostId());
			throw new BadRequestException("Error Message:" +oe.getMessage());
		} catch (ClientException ce) {
			log.error("Caught an ClientException, which means the client encountered "
					+ "a serious internal problem while trying to communicate with OSS, "
					+ "such as not being able to access the network.");
			throw new BadRequestException("Error Message:" +ce.getMessage());
		} finally {
			if (ossClient != null) {
				ossClient.shutdown();
			}
		}
	}

	public static void delete(AliStorageConfig aliStorageConfig, Collection<String> fileNames){
		// 创建OSSClient实例。
		OSS ossClient = new OSSClientBuilder().build(AliEndpointEnum.find(aliStorageConfig.getEndpoint()),
				aliStorageConfig.getAccessKeyId(), aliStorageConfig.getAccessKeySecret());

		try {
			// 删除文件或目录。如果要删除目录，目录必须为空。
			for (String fileName : fileNames) {
				ossClient.deleteObject(aliStorageConfig.getBucket(), PACKAGE_NAME+fileName);
			}
		} catch (OSSException oe) {
			log.error("Caught an OSSException, which means your request made it to OSS, "
					+ "but was rejected with an error response for some reason.");
			log.error("Error Message:" + oe.getErrorMessage());
			log.error("Error Code:" + oe.getErrorCode());
			log.error("Request ID:" + oe.getRequestId());
			log.error("Host ID:" + oe.getHostId());
		} catch (ClientException ce) {
			log.error("Caught an ClientException, which means the client encountered "
					+ "a serious internal problem while trying to communicate with OSS, "
					+ "such as not being able to access the network.");
			log.error("Error Message:" + ce.getMessage());
		} finally {
			if (ossClient != null) {
				ossClient.shutdown();
			}
		}
	}

	public static void pageQuery(AliStorageConfig aliStorageConfig){
		// 设置每页列举200个文件。
		int maxKeys = 200;

		// 创建OSSClient实例。
		OSS ossClient = new OSSClientBuilder().build(aliStorageConfig.getEndpoint(), aliStorageConfig.getAccessKeyId(),
				aliStorageConfig.getAccessKeySecret());

		try {
			String nextMarker = null;
			ObjectListing objectListing;

			do {
				objectListing = ossClient.listObjects(new ListObjectsRequest(aliStorageConfig.getBucket()).
						withMarker(nextMarker).withMaxKeys(maxKeys));

				List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
				for (OSSObjectSummary s : sums) {
					log.error("\t" + s.getKey());
				}

				nextMarker = objectListing.getNextMarker();

			} while (objectListing.isTruncated());
		} catch (OSSException oe) {
			log.error("Caught an OSSException, which means your request made it to OSS, "
					+ "but was rejected with an error response for some reason.");
			log.error("Error Message:" + oe.getErrorMessage());
			log.error("Error Code:" + oe.getErrorCode());
			log.error("Request ID:" + oe.getRequestId());
			log.error("Host ID:" + oe.getHostId());
		} catch (ClientException ce) {
			log.error("Caught an ClientException, which means the client encountered "
					+ "a serious internal problem while trying to communicate with OSS, "
					+ "such as not being able to access the network.");
			log.error("Error Message:" + ce.getMessage());
		} finally {
			if (ossClient != null) {
				ossClient.shutdown();
			}
		}
	}
}
